package com.powernode.common.aop;

import com.powernode.common.constant.RedisConstant;
import com.powernode.common.execption.PowerException;
import com.powernode.common.result.ResultCodeEnum;
import com.powernode.common.util.AuthContextHolder;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 切面类
 * 处理用户id
 * 1.获取request对象
 * 2.从request中获取token
 * 3.根据token从redis中获取用户id
 * 4.将用户id设置到ThreadLocal中,AuthContextHolder
 */
@Aspect
@Component
public class PowerLoginAspect {
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 切入点表达式：1.匹配所有Controller   2.Controller上添加PowerLogin注解
     * @param joinPoint
     * @return
     */
    @Around("execution(* com.powernode.*.controller.*.*(..)) && @annotation(com.powernode.common.annotation.PowerLogin)")
    public Object process(ProceedingJoinPoint joinPoint) throws Throwable {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //1.获取request对象
        ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();

        //2.从request中获取token
        String token = request.getHeader("token");

        if(!StringUtils.hasText(token)) {
            throw new PowerException(ResultCodeEnum.LOGIN_AUTH);
        }

        //3.根据token从redis中获取用户id
        String userId = (String)redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX+token);

        //4.将用户id设置到ThreadLocal中,AuthContextHolder
        //本质：将userId存入ThreadLocal中
        AuthContextHolder.setUserId(Long.parseLong(userId));

        return joinPoint.proceed();
    }

}
